package vip.xiaonuo.hontu.issued.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import java.util.Optional;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.stereotype.Service;
import vip.xiaonuo.core.exception.ServiceException;
import vip.xiaonuo.facedoor.iservice.IDeviceSetService;
import vip.xiaonuo.facedoor.iservice.IFaceDoorDtoService;
import vip.xiaonuo.facedoor.modular.devicebase.entity.DeviceBase;
import vip.xiaonuo.facedoor.modular.devicebase.mapper.DeviceBaseMapper;
import vip.xiaonuo.facedoor.modular.deviceset.entity.DwDeviceSet;
import vip.xiaonuo.facedoor.modular.deviceset.param.DwDeviceSetParam;
import vip.xiaonuo.facedoor.modular.deviceset.service.DwDeviceSetService;
import vip.xiaonuo.facedoor.rule.HTRulesEngine;
import vip.xiaonuo.facedoor.rule.RuleConstant;
import vip.xiaonuo.facedoor.vo.haiqing.BaseResponse;
import vip.xiaonuo.facedoor.vo.haiqing.RebootDeviceRequest;
import vip.xiaonuo.facedoor.vo.haiqing.RequestHeader;
import vip.xiaonuo.hontu.issued.request.PubSubRequest;
import vip.xiaonuo.hontu.issued.response.HTBaseResponse;
import vip.xiaonuo.hontu.issued.util.HT_DEVICE_POST;
import vip.xiaonuo.hontu.issued.util.HongTuRequestUrl;

@Service(value =RuleConstant.HT + RuleConstant.DEVICE_SET)
@Slf4j
public class HTDeviceSetServiceImpl implements IDeviceSetService {

    @Resource
    private DeviceBaseMapper deviceBaseMapper;

    @Resource
    private DwDeviceSetService dwDeviceSetService;

    @Override
    public void saveOrUpdate(DwDeviceSetParam dwDeviceSetParam) {
        DeviceBase deviceBase = deviceBaseMapper.selectById(dwDeviceSetParam.getDeviceBaseId());
        if (deviceBase == null) {
            throw new ServiceException(500, "设备不存在！");
        }
        String uri = IFaceDoorDtoService.getBaseParam(dwDeviceSetParam.getIp(), Integer.parseInt(dwDeviceSetParam.getCabinetPort()));
        String password = Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin");
        RequestHeader requestHeader = new RequestHeader().setUserName("admin").setPassWord(password);
        try {
            DwDeviceSet deviceSet = dwDeviceSetService.getOne(new LambdaQueryWrapper<DwDeviceSet>()
                .eq(DwDeviceSet::getDeviceBaseId, dwDeviceSetParam.getDeviceBaseId()));
            // 新增
            if (deviceSet == null) {
                addDeviceSet(dwDeviceSetParam, uri, requestHeader);
                // 下发订阅信息
                uploadSubscribe(dwDeviceSetParam, uri, requestHeader, dwDeviceSetParam.getDeviceId());
                // ip 端口修改
                deviceBase.setCabinetIp(dwDeviceSetParam.getIp());
                deviceBase.setCabinetPort(dwDeviceSetParam.getCabinetPort());
                deviceBaseMapper.updateById(deviceBase);
                // 基础参数修改
            } else if (ObjectUtil.equal(dwDeviceSetParam.getUpdateType(),1)){
                // 基础参数修改
                updateBaseParam(dwDeviceSetParam, uri, requestHeader, deviceSet);
                // ip 端口修改
                deviceBase.setCabinetIp(dwDeviceSetParam.getIp());
                deviceBase.setCabinetPort(dwDeviceSetParam.getCabinetPort());
                // 下发订阅信息
                uploadSubscribe(dwDeviceSetParam, uri, requestHeader, deviceSet.getDeviceId());
                deviceBaseMapper.updateById(deviceBase);
            }else if (ObjectUtil.equal(dwDeviceSetParam.getUpdateType(),0)){
                // ip 端口修改
                deviceBase.setCabinetIp(dwDeviceSetParam.getIp());
                deviceBase.setCabinetPort(dwDeviceSetParam.getCabinetPort());
                // 下发订阅参数
                uploadSubscribe(dwDeviceSetParam, uri, requestHeader, deviceSet.getDeviceId());
                dwDeviceSetService.edit(dwDeviceSetParam);
                deviceBaseMapper.updateById(deviceBase);
            }
        } catch (Exception e) {
            throw new ServiceException(500, "发生异常！异常信息为：" + ExceptionUtils.getMessage(e));
        }
    }

    private void uploadSubscribe(DwDeviceSetParam dwDeviceSetParam, String uri, RequestHeader requestHeader, Integer deviceId) throws Exception {
        // 下发订阅参数
        PubSubRequest request = new PubSubRequest(dwDeviceSetParam);
        HTBaseResponse response = HT_DEVICE_POST.postJson(HongTuRequestUrl.POST_PUBSUB,
                dwDeviceSetParam.getIp(), dwDeviceSetParam.getCabinetPort(),request, HTBaseResponse.class);
        if(ObjectUtil.equal(response.getCode() , 0)){
            log.info("消息订阅成功");
        }else{
            throw new ServiceException(500,"订阅信息设置失败 失败信息： " + JSON.toJSONString(response));
        }
    }


    private void addDeviceSet(DwDeviceSetParam dwDeviceSetParam, String uri, RequestHeader requestHeader) throws Exception {
        //  新增时获取基础参数
        HTBaseResponse response = HT_DEVICE_POST.getJson(HongTuRequestUrl.GET_UUID_SWITCH, dwDeviceSetParam.getIp(), dwDeviceSetParam.getCabinetPort(), HTBaseResponse.class);
        if (response != null && response.getCode() == 0) {
            log.info("获取设备基础参数成功！");
            DwDeviceSet one = dwDeviceSetService.getOne(new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceId, dwDeviceSetParam.getDeviceBaseId()));
            if(one!=null){
                throw new ServiceException(500, "该设备已经存在 请检查！");
            }
            dwDeviceSetService.add(dwDeviceSetParam);
        } else {
            throw new ServiceException(500, "获取设备基础参数失败！");
        }
    }

    private void updateBaseParam(DwDeviceSetParam dwDeviceSetParam, String uri, RequestHeader requestHeader, DwDeviceSet deviceSet) throws Exception {
        //  判断参数是否正确
        HTBaseResponse response = HT_DEVICE_POST.getJson(HongTuRequestUrl.GET_UUID_SWITCH, dwDeviceSetParam.getIp(), dwDeviceSetParam.getCabinetPort(), HTBaseResponse.class);
        if (response != null && response.getCode() == 0) {
            log.info("设备参数正确！");
            BeanUtil.copyProperties(dwDeviceSetParam, deviceSet);
            dwDeviceSetService.updateById(deviceSet);
        } else {
            throw new ServiceException(500, "设备参数错误！请检查");
        }
    }

    @Override
    public void restart(String deviceId) {
        // 调用接口远程重启
        DeviceBase deviceBase = deviceBaseMapper.selectById(deviceId);
        if (deviceBase == null) {
            throw new ServiceException(500, "设备不存在！");
        }

        DwDeviceSet deviceSet = dwDeviceSetService.getOne(new LambdaQueryWrapper<DwDeviceSet>().eq(DwDeviceSet::getDeviceBaseId, deviceBase.getId()));
        if (deviceSet==null){
            throw new ServiceException(500,"设备尚未设置! ");
        }

        String uri = IFaceDoorDtoService.getBaseParam(deviceBase.getCabinetIp(), Integer.parseInt(deviceBase.getCabinetPort()));

        String password = Optional.ofNullable(deviceBase.getDevicePassword()).orElse("admin");

        RequestHeader requestHeader = new RequestHeader().setUserName("admin").setPassWord(password);

        RebootDeviceRequest.InfoDTO infoDTO = new RebootDeviceRequest.InfoDTO();
        infoDTO.setIsRebootDevice(1);
        infoDTO.setDeviceID(deviceSet.getDeviceId());

        RebootDeviceRequest rebootDeviceRequest = new RebootDeviceRequest();
        rebootDeviceRequest.setInfo(infoDTO);

        try {
            BaseResponse baseResponse = HTRulesEngine.faceDoorDtoService.rebootDevice(uri, rebootDeviceRequest, requestHeader);
            if (ObjectUtil.equal(baseResponse.getCode(), 200)) {
                log.info("设备重启成功！");
            } else {
                throw new ServiceException(
                    500,
                    "设备重启失败 失败信息： code:"
                        + baseResponse.getCode()
                        + " message:  "
                        + Optional.ofNullable(baseResponse.getInfo().getResult())
                        .orElse("")
                        + " "
                        + Optional.ofNullable(baseResponse.getInfo().getDetail())
                        .orElse(""));
            }
        }catch (Exception e) {
            throw new ServiceException(500, "发生异常！异常信息为：" + ExceptionUtils.getMessage(e));
        }
    }
}
